package com.fivehundredpx.greedo_layout_sample.slice;

import com.fivehundredpx.greedo_layout_sample.MeasUtils;
import com.fivehundredpx.greedo_layout_sample.ResourceTable;
import com.fivehundredpx.greedo_layout_sample.ultimateprovider.Model;
import com.fivehundredpx.greedo_layout_sample.ultimateprovider.UltimateProvider;
import com.fivehundredpx.greedo_layout_sample.view.ItemModel;
import com.fivehundredpx.greedolayout.GreedoLayoutSizeCalculator;
import com.fivehundredpx.greedolayout.Size;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.ListContainer;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.ImageInfo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 主页面
 *
 * @author hw
 * @since 2021/05/28
 */
public class SampleAbilitySlice extends AbilitySlice implements GreedoLayoutSizeCalculator.SizeCalculatorDelegate {
    private final static int[] IMAGES = {
            ResourceTable.Media_photo_1,
            ResourceTable.Media_photo_2,
            ResourceTable.Media_photo_3,
            ResourceTable.Media_photo_4,
            ResourceTable.Media_photo_5,
            ResourceTable.Media_photo_6,
            ResourceTable.Media_photo_7,
            ResourceTable.Media_photo_8,
            ResourceTable.Media_photo_9,
            ResourceTable.Media_photo_10,
            ResourceTable.Media_photo_11,
            ResourceTable.Media_photo_12,
            ResourceTable.Media_photo_13,
            ResourceTable.Media_photo_14,
            ResourceTable.Media_photo_15,
            ResourceTable.Media_photo_16,
            ResourceTable.Media_photo_17
    };
    private static final int IMAGE_COUNT = 500;

    //  宽度误差10px
    private static final int WIDTH_ERROR_RANGE = 10;

    //  可见区域前后3个item范围刷新
    private static final int ITEM_ERROR_RANGE = 3;

    private ListContainer mListContainer;
    private UltimateProvider mProvider;
    private List<Model> mModelList;
    private Button mToggleBt;
    private GreedoLayoutSizeCalculator mSizeCalculator;

    private boolean mIsToggleBtStateOn = false;
    private final int[] mImageResIds = IMAGES.clone();
    private final double[] mImageAspectRatios = new double[mImageResIds.length];

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        initComponet();
    }

    private void initComponet() {
        mModelList = new ArrayList<>();
        mToggleBt = (Button) findComponentById(ResourceTable.Id_toggleButton);
        mToggleBt.setClickedListener(component -> {
            mIsToggleBtStateOn = !mIsToggleBtStateOn;
            mToggleBt.setText(mIsToggleBtStateOn ? getString(ResourceTable.String_disable_fixed_height)
                    : getString(ResourceTable.String_enable_fixed_height));
            mModelList = getModels(mIsToggleBtStateOn ? true : false);
            mProvider.setModels(mModelList);
            // 全刷数据过多会卡死，采用局部刷新
            refreshVisibleItem();
        });
        mListContainer = (ListContainer) findComponentById(ResourceTable.Id_listContainer);
        calculateImageAspectRatios();
        mSizeCalculator = new GreedoLayoutSizeCalculator(this::aspectRatioForIndex);
        mSizeCalculator.setMaxRowHeight(MeasUtils.vpToPx(150, getContext()));
        mSizeCalculator.setContentWidth(MeasUtils.getDisplayWidthInPx(
                getContext()) - mListContainer.getPaddingLeft() - mListContainer.getPaddingRight());
        mModelList = getModels(false);
        mProvider = new UltimateProvider<Model>(mModelList, getContext());
        mProvider.setSpacing(MeasUtils.vpToPx(4, getContext()));
        mListContainer.setItemProvider(mProvider);
    }

    private void refreshVisibleItem() {
        // **第一个可见的位置**/
        int firstVisiblePosition = mListContainer.getFirstVisibleItemPosition();
        // **最后一个可见的位置**/
        int lastVisiblePosition = mListContainer.getLastVisibleItemPosition();
        int size = mModelList.size();
        for (int position = 0; position < size; position++) {
            // **在看见范围内才更新，不可见的滑动后自动会调用getComponent方法更新**/
            if (position >= firstVisiblePosition - ITEM_ERROR_RANGE && position <=
                    lastVisiblePosition + ITEM_ERROR_RANGE) {
                mProvider.notifyDataSetItemChanged(position);
            }
        }
    }

    /**
     * 获取集合数据
     *
     * @param fixedHeight 默认是false，点击变成true
     * @return List<Model> 集合数据model
     */
    public List<Model> getModels(boolean fixedHeight) {
        List<Model> list = new ArrayList<Model>();
        mSizeCalculator.setFixedHeight(fixedHeight);
        for (int i = 0; i < IMAGE_COUNT; i++) {
            mSizeCalculator.sizeForChildAtPosition(i);
        }
        Size size = null;
        List<Size> itemSizes = null;
        List<Integer> itemResIds = null;
        int width = mSizeCalculator.getContentWidth();
        for (int i = 0; i < IMAGE_COUNT; i++) {
            size = mSizeCalculator.sizeForChildAtPosition(i);
            if (itemSizes == null) {
                itemSizes = new ArrayList<>();
                itemResIds = new ArrayList<>();
            }
            itemSizes.add(size);
            itemResIds.add(i < mImageResIds.length ? mImageResIds[i] : mImageResIds[i % mImageResIds.length]);
            if (size.getWidth() < width && i != IMAGE_COUNT - 1 &&
                    Math.abs(width - size.getWidth()) > WIDTH_ERROR_RANGE) {
                width = width - size.getWidth();
            } else {
                list.add(new ItemModel(itemSizes, itemResIds));
                width = mSizeCalculator.getContentWidth();
                itemSizes = null;
                itemResIds = null;
            }
        }
        return list;
    }

    private void calculateImageAspectRatios() {
        for (int i = 0; i < mImageResIds.length; i++) {
            mImageAspectRatios[i] = getImageAspectRatios(mImageResIds[i]);
        }
    }

    private double getImageAspectRatios(int res) {
        try {
            Resource resource = getContext().getResourceManager().getResource(res);
            PixelMap mBitmap = ImageSource.create(resource, new ImageSource.SourceOptions()).createPixelmap(null);
            ImageInfo imageInfo = mBitmap.getImageInfo();
            int width = imageInfo.size.width;
            float height = imageInfo.size.height;
            return width / (double) height;
        } catch (NotExistException | IOException e) {
            e.printStackTrace();
        }
        return 1.0;
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    public double aspectRatioForIndex(int index) {
        if (index >= IMAGE_COUNT) {
            return 1.0;
        }
        return mImageAspectRatios[getLoopedIndex(index)];
    }

    private int getLoopedIndex(int index) {
        return index % IMAGES.clone().length; // wrap around
    }
}